from ctypes import *
from ctypes.wintypes import *

CF_UNICODETEXT = 13
CF_TEXT = 1
NULL = 0

'''
encoding 可等于 'gbk' 或者 'utf-8'
'''
encoding = "gbk"

kernel = windll.kernel32
user = windll.user32
msvcrt = cdll.msvcrt

strcpy = msvcrt.strcpy
strcpy.argtypes = [c_wchar_p,LPVOID]
strcpy.restype = c_wchar_p

CreateWindowExA = user.CreateWindowExA
CreateWindowExA.argtypes = [DWORD, LPCSTR, LPCSTR, DWORD, INT, INT,
                            INT, INT, HWND, HMENU, HINSTANCE, LPVOID]
CreateWindowExA.restype = HWND

DestroyWindow = user.DestroyWindow
DestroyWindow.argtypes = [HWND]
DestroyWindow.restype = BOOL

OpenClipboard = user.OpenClipboard
OpenClipboard.argtypes = [HWND]
OpenClipboard.restype = BOOL

EmptyClipboard = user.EmptyClipboard
EmptyClipboard.argtypes = []
EmptyClipboard.restype = BOOL

GlobalAlloc = kernel.GlobalAlloc
GlobalAlloc.argtypes = [UINT, c_size_t]
GlobalAlloc.restype = HGLOBAL

GlobalLock = kernel.GlobalLock
GlobalLock.argtypes = [HGLOBAL]
GlobalLock.restype = LPVOID

GlobalUnlock = kernel.GlobalUnlock
GlobalUnlock.argtypes = [HGLOBAL]
GlobalUnlock.restype = BOOL

SetClipboardData = user.SetClipboardData
SetClipboardData.argtypes = [UINT, HANDLE]
SetClipboardData.restype = HANDLE

CloseClipboard = user.CloseClipboard
CloseClipboard.argtypes = []
CloseClipboard.restype = BOOL

GetClipboardData = user.GetClipboardData
GetClipboardData.argtypes = [UINT]
GetClipboardData.restype = HANDLE

def copy_to_clipboard(buff):

    '''
    再某些版本的Windows中,比如笔者的Windows10PRO中,会需要一个有效的句柄.
    '''
    hw = CreateWindowExA(NULL, b"STATIC", None, NULL, NULL, NULL, NULL, NULL,
                         None, None, None, None)

    OpenClipboard(hw)
    EmptyClipboard()

    text = create_string_buffer(buff.encode(encoding))
    size = sizeof(text)
    hm = GlobalAlloc(0x0002, size)
    looked_hm = GlobalLock(hm)
    memmove(c_wchar_p(looked_hm), text, size)

    GlobalUnlock(hm)
    SetClipboardData(CF_TEXT, hm)
    CloseClipboard()
    DestroyWindow(hw)

def get_clipboard_text():
    OpenClipboard(NULL)
    handle =  GetClipboardData(CF_TEXT)
    if handle is None:
        CloseClipboard()
        raise ValueError("Unsupport format")
    lock_handle = GlobalLock(handle)
    buffer = string_at(lock_handle)
    GlobalUnlock(handle)
    CloseClipboard()
    return buffer.decode(encoding)

if __name__ == '__main__':
    copy_to_clipboard("你好呀")
    print(get_clipboard_text())